Skip to content

[await-dictionary] add failure case and edge case tests#5041

Merged
Ms2ger merged 4 commits into
tc39:mainfrom
danialasaria:dasaria/await-dictionary-keyed-failure-edge-tests
Jun 4, 2026
Merged

[await-dictionary] add failure case and edge case tests#5041
Ms2ger merged 4 commits into
tc39:mainfrom
danialasaria:dasaria/await-dictionary-keyed-failure-edge-tests

Conversation

@danialasaria

@danialasaria danialasaria commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR adds the remaining failure-case and edge-case coverage for the await-dictionary proposal's Promise keyed combinators:

  • Promise.allKeyed
  • Promise.allSettledKeyed

It follows the runtime/behavioral tests PR (#4932) and completes the testing plan from #4886.

What this PR covers

NewPromiseCapability failures (sync throws)

  • Constructor body throws (ctx-ctor-throws.js)
  • Executor does not provide callable resolve/reject in various combinations (capability-executor-not-callable.js)

GetPromiseResolve failures (async rejections)

  • Get(constructor, "resolve") accessor throws (invoke-resolve-get-error-reject.js)
  • Calling the resolved promiseResolve function throws (invoke-resolve-error-reject.js)

Invoke(then) failures (async rejections)

  • Get(nextPromise, "then") accessor throws (invoke-then-get-error-reject.js)
  • Calling nextPromise.then(...) throws (invoke-then-error-reject.js)

allKeyed rejection ordering

  • Second promise to settle is rejected (reject-second.js)
  • Last promise to settle is rejected (reject-last.js)

Synchronous thenables (step 8 edge case)

  • Thenables that synchronously invoke onFulfilled during the loop, causing remainingElementsCount to reach zero before the loop exits (resolve-before-loop-exit.js)

Exotic object abrupt completions (Proxy)

  • [[OwnPropertyKeys]] throws (ownkeys-throws.js)
  • [[GetOwnProperty]] throws (getownproperty-throws.js)
  • [[GetOwnProperty]] returns undefined -- key is skipped (getownproperty-returns-undefined.js)

Property descriptor filtering

  • Non-enumerable keys are skipped (getownproperty-not-enumerable.js)

Notes

  • All async tests use asyncTest from asyncHelpers.js per reviewer feedback on [await-dictionary] add runtime keyed Promise combinator tests #4932
  • Sync tests use assert.throws(...)
  • All tests are feature-gated with features: [await-dictionary]; Proxy tests additionally gate on Proxy
  • Tests mirror existing patterns from Promise.all / Promise.allSettled test suites
  • capability-executor-not-callable includes poisoned resolve getters (matching Promise.all counterpart) to detect wrong evaluation order

What this PR does not cover

This completes all items from the testing plan (#4886).

References

@danialasaria danialasaria force-pushed the dasaria/await-dictionary-keyed-failure-edge-tests branch from 578f02d to 6e2fa0c Compare April 29, 2026 18:05
@danialasaria danialasaria marked this pull request as ready for review April 29, 2026 18:11
@danialasaria danialasaria requested a review from a team as a code owner April 29, 2026 18:11

@acutmore acutmore left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we also have a test that a custom constructor is being 'constructed' rather than 'called'.

If we can use new.target we can check like:

var error = new Test262Error();
function Constructor(executor) {
  if (new.target !== Constructor) {
    throw error
  }
}

We can also have assertions that validate the arguments passed to a custom constructor are correct: should only be one argument: the executor. And it should be a function with length 2.


Promise.allSettledKeyed.call(Constructor, input);

assert.sameValue(callCount, 1, "callCount after call to allSettledKeyed()");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we either move the callCount to after the assertions, or have a separate count for the start and end of the callback. Otherwise technically the assertions could reject and they are swallowed by the function caller yet the test would pass (unless the harness has some tracking logic to guarantee a test fails if a harness assertion errors, rather than relying on the exception bubbling up)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed by replacing the single counter with resolveStartCount and resolveEndCount. The end counter is incremented only after the resolve callback assertions complete, so an assertion failure inside the callback won’t be hidden by the final count check.

Cover remaining items from the testing plan (tc39#4886):

- NewPromiseCapability: constructor throws, executor not callable
- NewPromiseCapability: validate Construct (new.target, executor arity)
- GetPromiseResolve: Get accessor throws, promiseResolve call throws
- Invoke(then): Get accessor throws, call throws
- allKeyed rejection ordering (2nd and last to settle)
- Synchronous thenables hitting remainingElementsCount step 8
- Exotic object: [[OwnPropertyKeys]] throws
- Exotic object: [[GetOwnProperty]] throws / returns undefined
- Property descriptor filtering: non-enumerable keys skipped
@danialasaria danialasaria force-pushed the dasaria/await-dictionary-keyed-failure-edge-tests branch from 6e2fa0c to 85ec0d4 Compare May 9, 2026 22:14
Comment on lines +28 to +30
ownKeys: function() {
return ['key'];
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not harmful but also feels superfluous to the test as ownKeys will already be returning this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the explicit ownKeys trap. The Proxy target already has an own enumerable key property, so default [[OwnPropertyKeys]] still exposes the key while the test remains focused on the custom getOwnPropertyDescriptor behavior.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still seeing the ownKeys trap. Did you forget to push?

Comment on lines +22 to +24
ownKeys: function() {
return ['key'];
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed here as well--removed the redundant ownKeys trap

@danialasaria

Copy link
Copy Markdown
Contributor Author

Could we also have a test that a custom constructor is being 'constructed' rather than 'called'.

If we can use new.target we can check like:

var error = new Test262Error();
function Constructor(executor) {
  if (new.target !== Constructor) {
    throw error
  }
}

We can also have assertions that validate the arguments passed to a custom constructor are correct: should only be one argument: the executor. And it should be a function with length 2.

Added ctx-ctor-constructed.js coverage for both Promise.allKeyed and Promise.allSettledKeyed. The custom constructor checks new.target, verifies it receives exactly one argument, confirms the executor is callable, and asserts executor.length === 2.

@danialasaria danialasaria requested a review from acutmore May 29, 2026 14:47

@Ms2ger Ms2ger left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't get through it yet, but here are some initial comments.

Comment thread test/built-ins/Promise/allKeyed/ctx-ctor-constructed.js
Comment thread test/built-ins/Promise/allKeyed/getownproperty-not-enumerable.js
Comment thread test/built-ins/Promise/allKeyed/getownproperty-returns-undefined.js Outdated
Comment thread test/built-ins/Promise/allKeyed/invoke-then-error-reject.js Outdated
Comment thread test/built-ins/Promise/allKeyed/invoke-then-get-error-reject.js Outdated
@Ms2ger Ms2ger self-assigned this Jun 2, 2026

@Ms2ger Ms2ger left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address the previous comments in the analogous allSettledKeyed tests as well.

Comment on lines +28 to +30
ownKeys: function() {
return ['key'];
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still seeing the ownKeys trap. Did you forget to push?

Add missing feature metadata, align Invoke(then) spec excerpts, and remove redundant ownKeys traps from getOwnProperty tests.
@danialasaria

Copy link
Copy Markdown
Contributor Author

Please address the previous comments in the analogous allSettledKeyed tests as well.

Should be all updated now!

@danialasaria danialasaria requested a review from Ms2ger June 3, 2026 16:02
Add assertion messages for getOwnProperty tests where skipped keys produce an empty result object.
@Ms2ger Ms2ger merged commit 05bb032 into tc39:main Jun 4, 2026
9 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants